package autumn

import (
	"fmt"
	"reflect"

	"go.uber.org/zap"
)

var structs []interface{} = make([]interface{}, 0)
var components map[reflect.Type]interface{} = make(map[reflect.Type]interface{})

func Register(structBean interface{}) {
	rType := reflect.TypeOf(structBean)
	currBean, ok := components[rType]
	if ok {
		if currBean != structBean {
			zap.L().Error(fmt.Sprintf("Register duplicate structBean of type %s", rType.Name()))
		} else {
			return
		}
	}
	structs = append(structs, structBean)
	components[rType] = structBean
}

// 调用函数例子：GetStructLike((*IModuleService)(nil))
func GetStructLike[T interface{}](t *T) []T {
	interfaceType := reflect.TypeOf(t).Elem()

	results := make([]T, 0)
	for _, structBean := range structs {
		if reflect.TypeOf(structBean).Implements(interfaceType) {
			results = append(results, structBean.(T))
		}
	}
	return results
}

func Inject(structBean interface{}) {
	rType := reflect.TypeOf(structBean).Elem()
	rValue := reflect.ValueOf(structBean).Elem()
	for i := 0; i < rType.NumField(); i++ {
		rtField := rType.Field(i)
		rTag := rtField.Tag
		_, ok := rTag.Lookup("autowire")
		if !ok {
			continue
		}
		component, ok := components[rtField.Type]
		if !ok {
			zap.L().Error("Can not find component of \"" + rtField.Name + "\" in \"" + rType.Name() + "\"")
			continue
		}
		rvField := rValue.Field(i)
		rvField.Set(reflect.ValueOf(component))
		zap.L().Error("Autowire \"" + rtField.Name + "\" in \"" + rType.Name() + "\"")
	}
}
